//
//  DFDiff.m
//  dfCommandBuilder
//
//  Created by Tom Booth on 01/06/2009.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "DFDiff.h"

@interface DFDiff (PrivateMethods)

- (void) diffCommand:(DFCommand*) c1 :(DFCommand*) c2;
- (void) diffParameters:(NSArray*) p1 :(NSArray*) p2 :(NSString*) name;
- (void) diffParameter:(DFParameter*) p1 :(DFParameter*) p2 :(NSString*) name;

- (NSString*) stringifyBool:(BOOL) b;

@end


@implementation DFDiff

- (void) run:(NSArray*)commands1 :(NSArray*) commands2 {
	
	NSMutableArray *diffBuffer = [[NSMutableArray alloc] initWithArray:commands2 copyItems:false];
	
	for (DFCommand *c in commands1) {
		NSUInteger index = [diffBuffer indexOfObject:c];
		if (index!=NSNotFound) {
			//good stuff
			[self diffCommand:c :[diffBuffer objectAtIndex:index]];
			
			[diffBuffer removeObject:c];
		}
		else {
			fprintf(stdout, "Function %s has been added\n", [c.name cStringUsingEncoding:NSASCIIStringEncoding]);
		}
	}
	
	for (DFCommand *c in diffBuffer) {
		fprintf(stdout, "Function %s has been removed\n", [c.name cStringUsingEncoding:NSASCIIStringEncoding]);
	}
	
}


- (void) diffCommand:(DFCommand*) c1 :(DFCommand*) c2 {
	
	// check description
	if ([[c1 description] compare:[c2 description]] != NSOrderedSame) {
		fprintf(stdout, "New: %s description reads:%s\n", [c1.name cStringUsingEncoding:NSASCIIStringEncoding], [c1.description cStringUsingEncoding:NSASCIIStringEncoding]);
		fprintf(stdout, "Old: %s description reads:%s\n", [c2.name cStringUsingEncoding:NSASCIIStringEncoding], [c2.description cStringUsingEncoding:NSASCIIStringEncoding]);
	}
	
	// check returnsrows
	if (c1.returnsRows != c2.returnsRows) {
		fprintf(stdout, "New: %s returnsRows value is %s\n", [c1.name cStringUsingEncoding:NSASCIIStringEncoding], [[self stringifyBool:[c1 returnsRows]] cStringUsingEncoding:NSASCIIStringEncoding]);
		fprintf(stdout, "Old: %s returnsRows value is %s\n", [c2.name cStringUsingEncoding:NSASCIIStringEncoding], [[self stringifyBool:[c2 returnsRows]] cStringUsingEncoding:NSASCIIStringEncoding]);
	}
	
	// check createsrows
	if (c1.createsRows != c2.createsRows) {
		fprintf(stdout, "New: %s createsRows value is %s\n", [c1.name cStringUsingEncoding:NSASCIIStringEncoding], [[self stringifyBool:[c1 createsRows]] cStringUsingEncoding:NSASCIIStringEncoding]);
		fprintf(stdout, "Old: %s createsRows value is %s\n", [c2.name cStringUsingEncoding:NSASCIIStringEncoding], [[self stringifyBool:[c2 createsRows]] cStringUsingEncoding:NSASCIIStringEncoding]);
	}
	
	// check parameters
	[self diffParameters:[c1 getParameters] :[c2 getParameters] :[NSString stringWithFormat:@"%@ (%@)", c1.name, @"parameter"]];
	
	// check returnparameters
	[self diffParameters:[c1 getReturnParameters] :[c2 getReturnParameters] :[NSString stringWithFormat:@"%@ (%@)", c1.name, @"returnparameter"]];
	
	// check rowparameters
	[self diffParameters:[c1 getRowParameters] :[c2 getRowParameters] :[NSString stringWithFormat:@"%@ (%@)", c1.name, @"rowparameter"]];
}

- (void) diffParameters:(NSArray*) p1 :(NSArray*) p2 :(NSString*) name {
	
	NSMutableArray *diffBuffer = [[NSMutableArray alloc] initWithArray:p2 copyItems:false];
	
	int i = 0;
	int index = 0;
	for (DFParameter *p in p1) {
		// check existance in p2
		index = [p2 indexOfObject:p];
		if (index!=NSNotFound) {
			// check for position
			if (i!=index) {
				fprintf(stdout, "New: %s [%s] is in position %d\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p.name cStringUsingEncoding:NSASCIIStringEncoding], i);
				fprintf(stdout, "Old: %s [%s] is in position %d\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p.name cStringUsingEncoding:NSASCIIStringEncoding], index);
			}
			
			// diff the parameters
			[self diffParameter:p :[p2 objectAtIndex:index] :name];
			
			[diffBuffer removeObject:p];
		}
		else {
			fprintf(stdout, "%s [%s] has been added at position %d\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p.name cStringUsingEncoding:NSASCIIStringEncoding], i);
		}
		
		
		i++;
	}
	
	// display remaining in diffBuffer
	for (DFParameter *p in diffBuffer) {
		fprintf(stdout, "%s [%s] has been removed\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p.name cStringUsingEncoding:NSASCIIStringEncoding]);
	}
	
}

- (void) diffParameter:(DFParameter*) p1 :(DFParameter*) p2 :(NSString*) name {
	
	// check description
	if ([[p1 description] compare:[p2 description]] != NSOrderedSame) {
		fprintf(stdout, "New: %s [%s] description reads:%s\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p1.name cStringUsingEncoding:NSASCIIStringEncoding], [p1.description cStringUsingEncoding:NSASCIIStringEncoding]);
		fprintf(stdout, "Old: %s [%s] description reads:%s\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p2.name cStringUsingEncoding:NSASCIIStringEncoding], [p2.description cStringUsingEncoding:NSASCIIStringEncoding]);
	}
	
	// check type
	if (p1.type != p2.type) {
		fprintf(stdout, "New: %s [%s] type is %s\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p1.name cStringUsingEncoding:NSASCIIStringEncoding], [[DFParameter getStringFromType:p1.type] cStringUsingEncoding:NSASCIIStringEncoding]);
		fprintf(stdout, "Old: %s [%s] type is %s\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p2.name cStringUsingEncoding:NSASCIIStringEncoding], [[DFParameter getStringFromType:p2.type] cStringUsingEncoding:NSASCIIStringEncoding]);
	}
	
	// check useInResponse
	if (p1.useInResponse != p2.useInResponse) {
		fprintf(stdout, "New: %s [%s] type is %s\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p1.name cStringUsingEncoding:NSASCIIStringEncoding], [[self stringifyBool:[p1 useInResponse]] cStringUsingEncoding:NSASCIIStringEncoding]);
		fprintf(stdout, "Old: %s [%s] type is %s\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p2.name cStringUsingEncoding:NSASCIIStringEncoding], [[self stringifyBool:[p2 useInResponse]] cStringUsingEncoding:NSASCIIStringEncoding]);
	}
	
	// check manditory
	if (p1.manditory != p2.manditory) {
		fprintf(stdout, "New: %s [%s] manditory is %s\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p1.name cStringUsingEncoding:NSASCIIStringEncoding], [[self stringifyBool:[p1 manditory]] cStringUsingEncoding:NSASCIIStringEncoding]);
		fprintf(stdout, "Old: %s [%s] manditory is %s\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p2.name cStringUsingEncoding:NSASCIIStringEncoding], [[self stringifyBool:[p2 manditory]] cStringUsingEncoding:NSASCIIStringEncoding]);
	}
	
	// check isSearchNumber
	if (p1.isSearchNumber != p2.isSearchNumber) {
		fprintf(stdout, "New: %s [%s] isSearchNumber is %s\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p1.name cStringUsingEncoding:NSASCIIStringEncoding], [[self stringifyBool:[p1 isSearchNumber]] cStringUsingEncoding:NSASCIIStringEncoding]);
		fprintf(stdout, "Old: %s [%s] isSearchNumber is %s\n", [name cStringUsingEncoding:NSASCIIStringEncoding], [p2.name cStringUsingEncoding:NSASCIIStringEncoding], [[self stringifyBool:[p2 isSearchNumber]] cStringUsingEncoding:NSASCIIStringEncoding]);
	}
}

- (NSString*) stringifyBool:(BOOL) b {
	if (b) { return @"True"; }
	else { return @"False"; }
}

@end
